package parser.boc.bj08
import com.alipay.bcm.common.service.facade.model.PosKeyUnionID
import com.alipay.supergw.core.domain.shared.message.SupergwMessage
import com.alipay.supergw.core.service.message.model.parser.SignatureInfo
import com.alipay.supergw.core.domain.shared.message.SupergwMessage
import com.alipay.supergw.core.service.message.iso8583.ISOMessage
import com.alipay.supergw.core.service.message.model.parser.SignatureInfo
import com.alipay.supergw.core.service.message.parser.ISO8583MessageParser
import com.alipay.supergw.common.util.lang.StringUtil
import com.alibaba.common.logging.Logger
import org.apache.commons.lang.ArrayUtils
import com.alipay.supergw.common.util.lang.CoderUtil
import com.alipay.bcm.common.service.facade.model.PosKeyUnionID
import com.alipay.bcm.common.service.facade.model.enums.KeyTypeEnum
import com.alipay.supergw.core.service.message.util.POSUtil
import com.alipay.supergw.core.service.message.parser.POSMessageParser
import com.alipay.supergw.common.util.lang.ISOUtil
import com.alipay.sofa.platform.cache.impl.Hex
import com.alipay.supergw.core.domain.shared.exception.util.AssertUtil
import com.alipay.supergw.core.domain.shared.exception.code.ParserErrorCode

/**
 * 线下收单中行接入，消费回执
 * 
 * @author yanfen.liu
 * @version $Id: bocbj_08_0101.java, v 0.1 2012-3-28 20:27 yanfen.liu Exp $
 */
public class Bocbj_08_0101 extends POSMessageParser { 
    
    private final String instId = "BOC";
    private final String macAlgType = "DOUBLE_DES";  //MAC算法类型

    /** 
     * @see com.alipay.supergw.core.service.message.parser.ISO8583MessageParser#getParseRules()
     */
    @Override
    public String getParseRules() {
       return """            
        <message>
    <header length="7"></header>
    <field id="0" type="IFB_NUMERIC" length="4"   name="msgType"></field>
    <field id="1" type="IFB_BITMAP" length="8" />
    <field id="2" type="IFB_LLNUM" length="19" name="cardNo" pad="true"></field>
    <field id="3" type="IFB_NUMERIC" length="6" name="processCode"></field>
    <field id="4" type="IFB_NUMERIC" length="12" name="orderAmount"></field>       
    <field id="11" type="IFB_NUMERIC" length="6" name="outOrderNo"></field>  
    <field id="12" type="IFB_NUMERIC" length="6" name="transactionTime"></field>
    <field id="13" type="IFB_NUMERIC" length="4" name="transactionDate"></field>             
    <field id="24" type="IFB_NUMERIC" length="3" name="NII" pad="true"></field>  
    <field id="25" type="IFB_NUMERIC" length="2" name="serviceCode" ></field>   
    <field id="37" type="IF_CHAR" length="12" name="instReceiptNo"></field>
    <field id="38" type="IF_CHAR" length="6" name="authCode"></field>
    <field id="39" type="IF_CHAR" length="2" name="CHANNEL_RESPONSE_CODE"></field>        
    <field id="41" type="IF_CHAR" length="8" name="termId"></field>    
    <field id="42" type="IF_CHAR" length="15" name="merchantId"></field>
    <field id="44" type="IFB_LLCHAR" length="25" />
    <field id="48" type="IFB_LLLCHAR" length="999" ></field> 
    <field id="49" type="IFB_NUMERIC" length="3" name="orderCurrency" pad="true"></field>   
    <field id="54" type="IFB_LLLCHAR" length="100"></field>   
    <field id="61" type="IFB_LLLCHAR" length="27" name="customDomain"></field>  
    <field id="64" type="IFB_BINARY" length="8" name="signed"></field>
    </message>
        """
     }
    
    @Override
    protected SupergwMessage parse(ISOMessage message) {
        SupergwMessage gw = super.parse(message);
       
       
        String cardNo = gw.g("cardNo");
        if (StringUtil.isBlank(cardNo)) {
            throw new IllegalArgumentException("返回的卡号为空");
        }
        gw.addField("panIndex", encryptCardInfo(cardNo));
        
        String customDomain = gw.g("customDomain");
        if(customDomain.length() >= 9){
            gw.addField("batchNo", StringUtil.substring(customDomain, 0, 6));
            gw.addField("operator", StringUtil.substring(customDomain, 6, 9));
        }        
        
        //组装MAC摘要
        gw.addField("unsigned", getUnsigned(gw));
        
        return gw;
    }
    
    /**
    * @see com.alipay.supergw.core.service.message.parser.POSMessageParser#getKeyUnionID(com.alipay.supergw.core.domain.shared.message.SupergwMessage)
    */
   @Override
   protected PosKeyUnionID getKeyUnionID(SupergwMessage gw) {
       return POSUtil.composeUnionID(instId, gw.g("merchantId"), gw.g("termId"), KeyTypeEnum.ZAK
           .getBizCode());
  }
   
   /**
   * @see com.alipay.supergw.core.service.message.parser.AbstractMessageParser#composeSignature(com.alipay.supergw.core.domain.shared.message.SupergwMessage)
   */
  @Override
  protected SignatureInfo composeSignature(SupergwMessage gw) { 

      SignatureInfo info = new SignatureInfo(macAlgType, gw.g("signed"), gw.g("unsigned")); 
      gw.remove("signed");
      gw.remove("unsigned");
      return info;
  }

  /**
   * @see com.alipay.supergw.core.service.message.parser.POSMessageParser#checkMac(com.alipay.bcm.common.service.facade.model.PosKeyUnionID, com.alipay.supergw.core.service.message.model.parser.SignatureInfo)
   */
  @Override
  protected void checkMac(PosKeyUnionID keyId, SignatureInfo info) {
      String mac = posUtil.calMacHex(keyId, info.getCode(), info.getUnsigned());
      boolean isVerifyOK = StringUtil.equals(info.getSigned().substring(0,8), mac.substring(0,8));
      AssertUtil.isTrue(isVerifyOK, ParserErrorCode.VERIFY_ERROR);
  }
        
    /**
    * 组装MAC摘要
    * @param message
    * @return
    */
   private String getUnsigned(SupergwMessage gw) {      
        //2、3、4、11、12, 13, 49、38,39, 41
        StringBuffer mac = new StringBuffer();
        mac.append(formatField(gw.g("cardNo")));// PAN
        mac.append(gw.g("processCode")); // PROCESS_CODE
        mac.append(gw.g("orderAmount")); // Amount
        mac.append(gw.g("outOrderNo"));   // TraceNo
        if(!StringUtil.isBlank(gw.g("transactionTime"))){
            mac.append(gw.g("transactionTime"));//Time
        }
        
        if(!StringUtil.isBlank(gw.g("transactionDate"))){
            mac.append(gw.g("transactionDate"));// Date
        }
        
        mac.append(formatField(gw.g("orderCurrency")))// Currency
        
        if(!StringUtil.isBlank(gw.g("authCode"))){
            mac.append(toHex(gw.g("authCode")));// AuthCode
        }
        
        mac.append(toHex(gw.g("CHANNEL_RESPONSE_CODE")));// ResponeCode
        mac.append(toHex(gw.g("termId")));//TerminalId
        
        return mac.toString();
   }
   
   /**
    * 将字符转换为16进制的字符串
    */
   private String toHex(String target){
      if(StringUtil.isBlank(target)){
          return target;
      }
      
     return new String(Hex.encodeHex(target.getBytes()));
     
   }
   
   private String formatField(String value) {
       if (StringUtil.isBlank(value)) {
           return StringUtil.EMPTY_STRING;
       }       

      if(value.length()%2 == 1)
       { 
           return "0" + value;
           
       }
      else
       {
           return value;
       }
      
   }

}
